import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      // home: ScrollControllerTestRoute(),
      home: const MyHomePage(
        title: 'demo',
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: Column(
        // children 这里加 const 会报错，buildTwoListView不是const
        children: const <Widget>[
          ListTile(title: Text("商品列表")),
          Expanded(
            child: futureContainer(),
          ),
          Expanded(
            child: streamContainer(),
          ),
        ],
      ),
    );
  }
}

// future：FutureBuilder依赖的Future，通常是一个异步耗时任务。
// initialData：初始数据，用户设置默认数据。
// builder：Widget构建器；该构建器会在Future执行的不同阶段被多次调用，构建器签名如下：
// Function (BuildContext context, AsyncSnapshot snapshot)

// snapshot会包含当前异步任务的状态信息及结果信息 ，比如我们可以通过snapshot.connectionState获取异步任务的状态信息、通过snapshot.hasError判断异步任务是否有错误等等，完整的定义读者可以查看AsyncSnapshot类定义。

// 注意：示例的代码中，每次组件重新build 都会重新发起请求，因为每次的 future 都是新的，实践中我们通常会有一些缓存策略，常见的处理方式是在 future 成功后将 future 缓存，这样下次build时，就不会再重新发起异步任务。

// ConnectionState是一个枚举类
// enum ConnectionState {
//   /// 当前没有异步任务，比如[FutureBuilder]的[future]为null时
//   none,

//   /// 异步任务处于等待状态
//   waiting,

//   /// Stream处于激活状态（流上已经有数据传递了），对于FutureBuilder没有该状态。
//   active,

//   /// 异步任务已经终止.
//   done,
// }

Future<String> mockNetworkData() async {
  return Future.delayed(const Duration(seconds: 2), () => "我是从互联网上获取的数据");
}

class futureContainer extends StatelessWidget {
  const futureContainer({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: FutureBuilder<String>(
        future: mockNetworkData(),
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          // 请求已结束
          if (snapshot.connectionState == ConnectionState.done) {
            if (snapshot.hasError) {
              // 请求失败，显示错误
              return Text("Error: ${snapshot.error}");
            } else {
              // 请求成功，显示数据
              return Text("Contents: ${snapshot.data}");
            }
          } else {
            // 请求未结束，显示loading
            return CircularProgressIndicator();
          }
        },
      ),
    );
  }
}

// Stream 也是用于接收异步事件数据，和Future 不同的是，它可以接收多个异步操作的结果，它常用于会多次读取数据的异步任务场景，如网络内容下载、文件读写等。StreamBuilder正是用于配合Stream来展示流上事件（数据）变化的UI组件。
// 和FutureBuilder的构造函数只有一点不同：前者需要一个future，而后者需要一个stream
// 在实战中，凡是UI会依赖多个异步数据而发生变化的场景都可以使用StreamBuilder
// 使用Stream来实现每隔一秒生成一个数字:
Stream<int> counter() {
  return Stream.periodic(Duration(seconds: 1), (i) {
    return i;
  });
}

class streamContainer extends StatelessWidget {
  const streamContainer({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<int>(
      stream: counter(), //
      //initialData: ,// a Stream<int> or null
      builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
        if (snapshot.hasError) return Text('Error: ${snapshot.error}');
        switch (snapshot.connectionState) {
          case ConnectionState.none:
            return Text('没有Stream');
          case ConnectionState.waiting:
            return Text('等待数据...');
          case ConnectionState.active:
            return Text('active: ${snapshot.data}');
          case ConnectionState.done:
            return Text('Stream 已关闭');
        }
        return Text(''); // unreachable
      },
    );
  }
}
